﻿using Angle.Krill.Utils;
using Angle.Krill.WinFile;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Threading;
using System.Windows.Forms;

namespace Angle.Krill
{
    public partial class Files : DummyWindow
    {
        private string folderPath = string.Empty;
        private AntdUI.IContextMenuStripItem[] rightMenu = null;
        private List<object> selectItems = new List<object>();

        public string FolderPath
        {
            get { return this.folderPath; }
            set { this.folderPath = value; }
        }

        public Files(string folderPath) : this()
        {
            this.folderPath = folderPath;
        }

        public Files()
        {
            InitializeComponent();
            this.KeyPreview = true;
        }

        private void Files_Load(object sender, EventArgs e)
        {
            this.Icon = ImageHelper.ConvertToIcon(ImageHelper.FileIcon);

            this.InitializeRightMenu();
            this.InitializeTable();

            this.BindData();
        }

        private void BindData()
        {
            DirectoryInfo directoryInfo = new DirectoryInfo(this.folderPath);
            var files = FileHelper.GetFiles(directoryInfo);
            this.tableFiles.DataSource = this.ConvertToFileList(files);
        }

        private void InitializeRightMenu()
        {
            this.rightMenu = new AntdUI.IContextMenuStripItem[]
            {
                new AntdUI.ContextMenuStripItem("打开"){
                    Tag="OpenFile"
                },
                new AntdUI.ContextMenuStripItem("新建"){
                    Tag="New",
                    Sub= new AntdUI.IContextMenuStripItem[]
                    {
                        new AntdUI.ContextMenuStripItem("文件"){
                            Tag="NewFile",
                            Icon = ImageHelper.FileIcon,
                        },
                        new AntdUI.ContextMenuStripItem("文件夹"){
                            Tag="NewFolder",
                            Icon = ImageHelper.FolderIcon,
                        },
                    }
                },
                new AntdUI.ContextMenuStripItem("刷新"){
                    Tag="Refresh"
                },
                new AntdUI.ContextMenuStripItemDivider(),
                new AntdUI.ContextMenuStripItem("剪切","Ctrl+X"){
                    Tag="Cut"
                },
                new AntdUI.ContextMenuStripItem("复制","Ctrl+C"){
                    Tag="Copy"
                },
                new AntdUI.ContextMenuStripItem("粘贴","Ctrl+V"){
                    Tag="Paste"
                },
                new AntdUI.ContextMenuStripItemDivider(),
                new AntdUI.ContextMenuStripItem("在文件资源管理器打开"){
                    Icon = ImageHelper.OpenFolderIcon,
                    Tag="OpenToFileExplorer"
                },
                new AntdUI.ContextMenuStripItemDivider(),
                new AntdUI.ContextMenuStripItem("删除","Del"){
                    Icon = ImageHelper.RemoveIcon,
                    Tag="Del"
                },
            };
        }

        private void InitializeTable()
        {
            this.tableFiles.CtrlCKey = () =>
            {
                this.CopyFile();
            };
            this.tableFiles.Columns = new AntdUI.Column[] {
                new AntdUI.ColumnCheck("Check"){ Fixed=true},
                new AntdUI.Column("Name","文件名"){ Fixed=true},
                new AntdUI.Column("FileSize","大小",AntdUI.ColumnAlign.Right),
                //new AntdUI.Column("PhysicalPath","路径",AntdUI.ColumnAlign.Left),
                new AntdUI.Column("LastModifyDatetime","最近一次修改时间",AntdUI.ColumnAlign.Center){
                    Width="120",
                    LineBreak=true
                }
            };
        }

        private void tableFiles_CellClick(object sender, MouseEventArgs args, object record, int rowIndex, int columnIndex, Rectangle rect)
        {
            this.selectItems.Add(record);

            if (args.Button == MouseButtons.Right)
            {
                AntdUI.ContextMenuStrip.open(this.tableFiles, it =>
                {
                    if (it.Tag?.ToString() == "OpenToFileExplorer")
                    {
                        this.OpenToFileExplorer(record as FileList);
                    }
                    else if (it.Tag?.ToString() == "OpenFile")
                    {
                        this.OpenFile(record as FileList);
                    }
                    else if (it.Tag?.ToString() == "NewFile")
                    {
                        OperateFileHelper.Instance.NewFile((record as FileList).PhysicalPath, (f) =>
                        {
                            f.FormClosed += New_FormClosed;
                        });
                    }
                    else if (it.Tag?.ToString() == "NewFolder")
                    {
                        OperateFileHelper.Instance.NewFolder((record as FileList).PhysicalPath, (f) =>
                        {
                            f.FormClosed += New_FormClosed;
                        });
                    }
                    else if (it.Tag?.ToString() == "Refresh")
                    {
                        this.BindData();
                    }
                    else if (it.Tag?.ToString() == "Cut")
                    {
                        this.CutFile();
                    }
                    else if (it.Tag?.ToString() == "Copy")
                    {
                        this.CopyFile();
                    }
                    else if (it.Tag?.ToString() == "Paste")
                    {
                        this.PasteFile();
                    }
                    else if (it.Tag?.ToString() == "Del")
                    {
                        this.DelFile();
                    }
                }, this.rightMenu);
            }
        }

        private void New_FormClosed(object sender, FormClosedEventArgs e)
        {
            this.BindData();
        }

        private void tableFiles_KeyDown(object sender, KeyEventArgs e)
        {
        }

        private void Files_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.Modifiers == Keys.Control && e.KeyCode == Keys.X)
            {
                this.CutFile();
            }
            else if (e.Modifiers == Keys.Control && e.KeyCode == Keys.C)
            {
                this.CopyFile();
            }
            else if (e.Modifiers == Keys.Control && e.KeyCode == Keys.V)
            {
                this.PasteFile();
            }
            else if (e.KeyCode == Keys.Delete)
            {
                this.DelFile();
            }
            e.Handled = true;
        }

        private void CutFile()
        {
            var lst = this.tableFiles.GetSelectRow<FileList>();
            OptFile optFile = new OptFile
            {
                Files = lst,
                Opt = "cut"
            };
            Clipboard.SetText(CodeHelper.Base64Encrypt(JsonConvert.SerializeObject(optFile)));
        }

        private void CopyFile()
        {
            var lst = this.tableFiles.GetSelectRow<FileList>();
            OptFile optFile = new OptFile
            {
                Files = lst,
                Opt = "copy"
            };
            Clipboard.SetText(CodeHelper.Base64Encrypt(JsonConvert.SerializeObject(optFile)));
        }

        private void PasteFile()
        {
            string s = Clipboard.GetText();

            if (string.IsNullOrEmpty(s))
            {
                AntdUI.Message.info(this, $"剪贴板未找到信息", Font);
                return;
            }

            OptFile optFile = JsonConvert.DeserializeObject<OptFile>(CodeHelper.Base64Decrypt(s));

            if (optFile.Opt == "copy")
            {
                foreach (var f in optFile.Files)
                {
                    FileHelper.CopyFile(this.folderPath, f.PhysicalPath, (fileName) =>
                    {
                        bool isCover = false;
                        AntdUI.Modal.open(new AntdUI.Modal.Config(this.ParentForm, "提示", $"{fileName}\t\n存在相同名称文件，确认进行覆盖？", AntdUI.TType.Warn)
                        {
                            OnOk = config =>
                            {
                                isCover = true;

                                return true;
                            }
                        });

                        return isCover;
                    });
                }

                this.BindData();
            }
            else if (optFile.Opt == "cut")
            {
                foreach (var f in optFile.Files)
                {
                    FileHelper.MoveFile(this.folderPath, f.PhysicalPath);
                }

                this.BindData();
            }

            return;
        }

        private void DelFile()
        {
            var lst = this.tableFiles.GetSelectRow<FileList>();

            OperateFileHelper.Instance.DelFile(lst, this.ParentForm, () =>
            {
                this.BindData();
            }, fileLockCallback);
        }

        private void tableFiles_CellDoubleClick(object sender, MouseEventArgs args, object record, int rowIndex, int columnIndex, Rectangle rect)
        {
            this.OpenFile(record as FileList);
        }
        /// <summary>
        /// 打开文件
        /// </summary>
        /// <param name="fileInfo"></param>
        private void OpenFile(FileList fileInfo)
        {
            if (string.IsNullOrEmpty(fileInfo?.PhysicalPath))
            {
                return;
            }

            FileHelper.ProcessStart(fileInfo.PhysicalPath, fileLockCallback);
        }

        private void fileLockCallback()
        {
            AntdUI.Message.info(this.ParentForm, "文件已被占用!", Font);
        }

        private void OpenToFileExplorer(FileList fileInfo)
        {
            if (string.IsNullOrEmpty(fileInfo?.PhysicalPath))
            {
                return;
            }

            FileHelper.ProcessStart(new ProcessStartInfo
            {
                Arguments = Path.GetDirectoryName(fileInfo.PhysicalPath),
                FileName = "explorer.exe"
            });
        }

        private List<FileList> ConvertToFileList(List<FileInfoExt> files)
        {
            var lstFile = AutoMapperHelper.AutoMapperToList<FileInfoExt, FileList>(files);

            return lstFile;
        }
    }

    public class OptFile
    {
        public string Opt { get; set; }
        public List<FileList> Files { get; set; }
    }

    [Serializable]
    public class FileList : MultipleSelectTable
    {
        /// <summary>
        /// 文件名称
        /// </summary>
        public string Name { get; set; }
        /// <summary>
        /// 没有扩展的文件名称
        /// </summary>
        public string NameWithoutExtend { get; set; }
        /// <summary>
        /// 相对路径
        /// </summary>
        public string RelativePath { get; set; }
        /// <summary>
        /// 绝对路径
        /// </summary>
        public string PhysicalPath { get; set; }
        public long? Size { get; set; }

        /// <summary>
        /// 最后修改时间
        /// </summary>
        public DateTime? LastModifyDatetime { get; set; }
        /// <summary>
        /// 备注
        /// </summary>
        public string Remark { get; set; }

        public string FileSize
        {
            get
            {
                double size = this.Size ?? 0;
                string unit = "B";
                if (size > 1024 * 1024 * 1024)
                {
                    size = size / (1024 * 1024 * 1024);
                    unit = "G";
                }
                else if (size > 1024 * 1024)
                {
                    size = size / (1024 * 1024);
                    unit = "M";
                }
                else if (size > 1024)
                {
                    size = size / 1024;
                    unit = "K";
                }

                return $"{size.ToString("f2")} {unit}";
            }
        }
    }
}
